#include "asio.hpp"
#include <iostream>
#include <list>
#include <chrono>

using asio::ip::tcp;

int main(int argc, char* argv[])
{
    const char * host = "127.0.0.1";
    const char * port = "8888";
    int max_connection_count = 5000;
    if(argc > 2) { host = argv[1]; }
    if(argc > 3) { port = argv[2]; }
    if(argc > 4) { port = argv[3]; }

    std::list<std::shared_ptr<tcp::socket>> connections;

    try
    {
        asio::io_context io_context(1);
        tcp::resolver resolver(io_context);
        tcp::resolver::results_type endpoints = resolver.resolve(host, port);
        auto start_time = std::chrono::steady_clock::now();
        while(true)
        {
            if(connections.size() < max_connection_count)
            {
                std::shared_ptr<tcp::socket> new_socket = std::make_shared<tcp::socket>(io_context);
                asio::async_connect(*new_socket.get(), endpoints,
                                    [&connections, new_socket]
                                    (const asio::error_code & ec, const tcp::endpoint & endpoint)
                {
                    if(ec)
                    {
                        std::cerr << "async_connect error:" << ec.message() << std::endl;
                    }
                    else
                    {
                        connections.emplace_back(new_socket);
                    }
                });
            }
            else
            {
                static bool has_print = false;
                if(!has_print)
                {
                    auto end_time = std::chrono::steady_clock::now();
                    double ms = (double)std::chrono::duration_cast<std::chrono::milliseconds>
                                (end_time - start_time).count();
                    std::cout << "speed : " << connections.size() / ms * 1000.f << std::endl;
                    has_print = true;
                }
            }
            io_context.poll();
        }
    }
    catch(const std::exception& e)
    {
        std::cerr << "exception: " << e.what() << "\n";
    }
    return 0;
}